<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>

<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title>StereoBM</title>
    <style type="text/css">  
        .container{  
           width:200px;  
           border:1px solid #02085e;  
           height:25px;  
         }
        #bar{  
           background:#02085e;  
           float:left; 
           height:100%;  
           text-align:center;  
           line-height:150%; 
         }  
        </style>  
    <script id="bm_worker" type="text/javascript" charset="utf-8">

        var color_map_r = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.00588235294117645, 0.02156862745098032, 0.03725490196078418, 0.05294117647058827, 0.06862745098039214, 0.084313725490196, 0.1000000000000001, 0.115686274509804, 0.1313725490196078, 0.1470588235294117, 0.1627450980392156, 0.1784313725490196, 0.1941176470588235, 0.2098039215686274, 0.2254901960784315, 0.2411764705882353, 0.2568627450980392, 0.2725490196078431, 0.2882352941176469, 0.303921568627451, 0.3196078431372549, 0.3352941176470587, 0.3509803921568628, 0.3666666666666667, 0.3823529411764706, 0.3980392156862744, 0.4137254901960783, 0.4294117647058824, 0.4450980392156862, 0.4607843137254901, 0.4764705882352942, 0.4921568627450981, 0.5078431372549019, 0.5235294117647058, 0.5392156862745097, 0.5549019607843135, 0.5705882352941174, 0.5862745098039217, 0.6019607843137256, 0.6176470588235294, 0.6333333333333333, 0.6490196078431372, 0.664705882352941, 0.6803921568627449, 0.6960784313725492, 0.7117647058823531, 0.7274509803921569, 0.7431372549019608, 0.7588235294117647, 0.7745098039215685, 0.7901960784313724, 0.8058823529411763, 0.8215686274509801, 0.8372549019607844, 0.8529411764705883, 0.8686274509803922, 0.884313725490196, 0.8999999999999999, 0.9156862745098038, 0.9313725490196076, 0.947058823529412, 0.9627450980392158, 0.9784313725490197, 0.9941176470588236, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.9862745098039216, 0.9705882352941178, 0.9549019607843139, 0.93921568627451, 0.9235294117647062, 0.9078431372549018, 0.892156862745098, 0.8764705882352941, 0.8607843137254902, 0.8450980392156864, 0.8294117647058825, 0.8137254901960786, 0.7980392156862743, 0.7823529411764705, 0.7666666666666666, 0.7509803921568627, 0.7352941176470589, 0.719607843137255, 0.7039215686274511, 0.6882352941176473, 0.6725490196078434, 0.6568627450980391, 0.6411764705882352, 0.6254901960784314, 0.6098039215686275, 0.5941176470588236, 0.5784313725490198, 0.5627450980392159, 0.5470588235294116, 0.5313725490196077, 0.5156862745098039, 0.5];
        var color_map_g = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.001960784313725483, 0.01764705882352935, 0.03333333333333333, 0.0490196078431373, 0.06470588235294117, 0.08039215686274503, 0.09607843137254901, 0.111764705882353, 0.1274509803921569, 0.1431372549019607, 0.1588235294117647, 0.1745098039215687, 0.1901960784313725, 0.2058823529411764, 0.2215686274509804, 0.2372549019607844, 0.2529411764705882, 0.2686274509803921, 0.2843137254901961, 0.3, 0.3156862745098039, 0.3313725490196078, 0.3470588235294118, 0.3627450980392157, 0.3784313725490196, 0.3941176470588235, 0.4098039215686274, 0.4254901960784314, 0.4411764705882353, 0.4568627450980391, 0.4725490196078431, 0.4882352941176471, 0.503921568627451, 0.5196078431372548, 0.5352941176470587, 0.5509803921568628, 0.5666666666666667, 0.5823529411764705, 0.5980392156862746, 0.6137254901960785, 0.6294117647058823, 0.6450980392156862, 0.6607843137254901, 0.6764705882352942, 0.692156862745098, 0.7078431372549019, 0.723529411764706, 0.7392156862745098, 0.7549019607843137, 0.7705882352941176, 0.7862745098039214, 0.8019607843137255, 0.8176470588235294, 0.8333333333333333, 0.8490196078431373, 0.8647058823529412, 0.8803921568627451, 0.8960784313725489, 0.9117647058823528, 0.9274509803921569, 0.9431372549019608, 0.9588235294117646, 0.9745098039215687, 0.9901960784313726, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.9901960784313726, 0.9745098039215687, 0.9588235294117649, 0.943137254901961, 0.9274509803921571, 0.9117647058823528, 0.8960784313725489, 0.8803921568627451, 0.8647058823529412, 0.8490196078431373, 0.8333333333333335, 0.8176470588235296, 0.8019607843137253, 0.7862745098039214, 0.7705882352941176, 0.7549019607843137, 0.7392156862745098, 0.723529411764706, 0.7078431372549021, 0.6921568627450982, 0.6764705882352944, 0.6607843137254901, 0.6450980392156862, 0.6294117647058823, 0.6137254901960785, 0.5980392156862746, 0.5823529411764707, 0.5666666666666669, 0.5509803921568626, 0.5352941176470587, 0.5196078431372548, 0.503921568627451, 0.4882352941176471, 0.4725490196078432, 0.4568627450980394, 0.4411764705882355, 0.4254901960784316, 0.4098039215686273, 0.3941176470588235, 0.3784313725490196, 0.3627450980392157, 0.3470588235294119, 0.331372549019608, 0.3156862745098041, 0.2999999999999998, 0.284313725490196, 0.2686274509803921, 0.2529411764705882, 0.2372549019607844, 0.2215686274509805, 0.2058823529411766, 0.1901960784313728, 0.1745098039215689, 0.1588235294117646, 0.1431372549019607, 0.1274509803921569, 0.111764705882353, 0.09607843137254912, 0.08039215686274526, 0.06470588235294139, 0.04901960784313708, 0.03333333333333321, 0.01764705882352935, 0.001960784313725483, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
        var color_map_b = [0.5, 0.5156862745098039, 0.5313725490196078, 0.5470588235294118, 0.5627450980392157, 0.5784313725490196, 0.5941176470588235, 0.6098039215686275, 0.6254901960784314, 0.6411764705882352, 0.6568627450980392, 0.6725490196078432, 0.6882352941176471, 0.7039215686274509, 0.7196078431372549, 0.7352941176470589, 0.7509803921568627, 0.7666666666666666, 0.7823529411764706, 0.7980392156862746, 0.8137254901960784, 0.8294117647058823, 0.8450980392156863, 0.8607843137254902, 0.8764705882352941, 0.892156862745098, 0.907843137254902, 0.9235294117647059, 0.9392156862745098, 0.9549019607843137, 0.9705882352941176, 0.9862745098039216, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.9941176470588236, 0.9784313725490197, 0.9627450980392158, 0.9470588235294117, 0.9313725490196079, 0.915686274509804, 0.8999999999999999, 0.884313725490196, 0.8686274509803922, 0.8529411764705883, 0.8372549019607844, 0.8215686274509804, 0.8058823529411765, 0.7901960784313726, 0.7745098039215685, 0.7588235294117647, 0.7431372549019608, 0.7274509803921569, 0.7117647058823531, 0.696078431372549, 0.6803921568627451, 0.6647058823529413, 0.6490196078431372, 0.6333333333333333, 0.6176470588235294, 0.6019607843137256, 0.5862745098039217, 0.5705882352941176, 0.5549019607843138, 0.5392156862745099, 0.5235294117647058, 0.5078431372549019, 0.4921568627450981, 0.4764705882352942, 0.4607843137254903, 0.4450980392156865, 0.4294117647058826, 0.4137254901960783, 0.3980392156862744, 0.3823529411764706, 0.3666666666666667, 0.3509803921568628, 0.335294117647059, 0.3196078431372551, 0.3039215686274508, 0.2882352941176469, 0.2725490196078431, 0.2568627450980392, 0.2411764705882353, 0.2254901960784315, 0.2098039215686276, 0.1941176470588237, 0.1784313725490199, 0.1627450980392156, 0.1470588235294117, 0.1313725490196078, 0.115686274509804, 0.1000000000000001, 0.08431372549019622, 0.06862745098039236, 0.05294117647058805, 0.03725490196078418, 0.02156862745098032, 0.00588235294117645, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];


        function worker_bm(left_Mat, right_Mat) {
            var left_ImageGray = cvtColorRGBA2Gray(left_Mat);
            postMessage(1);
            var left_ImageSobel = sobel(left_ImageGray);
            postMessage(10);
            var right_ImageGray = cvtColorRGBA2Gray(right_Mat);
            postMessage(11);
            var right_ImageSobel = sobel(right_ImageGray);
            postMessage(20);
            var left = left_bm(left_ImageSobel, right_ImageSobel);
            postMessage(55);
            var right = right_bm(left_ImageSobel, right_ImageSobel);
            postMessage(90);
            var disp_out = left_right_check(left, right);
            postMessage(95);
            var disp = cvtColorGray2RGBA_ColorMap(disp_out);
            postMessage(100);
            return disp;
        }
        function Image_RGBA(_row, _col, _data, _buffer) {
            this.row = _row || 0;
            this.col = _col || 0;
            this.buffer = _buffer || new ArrayBuffer(_row * _col * 4);
            this.data = new Uint8ClampedArray(this.buffer);
            _data && this.data.set(_data);
        }
        function Image_GRAY(_row, _col, _data, _buffer) {
            this.row = _row || 0;
            this.col = _col || 0;
            this.buffer = _buffer || new ArrayBuffer(_row * _col);
            this.data = new Uint8ClampedArray(this.buffer);
            _data && this.data.set(_data);
        }
        function cvtColorRGBA2Gray(_src) {
            var row = _src.row,
                col = _src.col;
            var dst = new Image_GRAY(row, col);
            data = dst.data;
            data2 = _src.data;
            for (i = 0; i < _src.row * _src.col * 4; i++) {
                data[i] = (data2[i * 4] * 299 + data2[i * 4 + 1] * 587 + data2[i * 4 + 2] * 114) / 1000;
            }
            return dst;
        }
        function cvtColorGray2RGBA(_src) {
            var row = _src.row,
                col = _src.col;
            var dst = new Image_RGBA(row, col);
            data = dst.data;
            data2 = _src.data;
            for (i = 0; i < _src.row * _src.col * 4;) {
                data[i++] = data2[i / 4];
                data[i++] = data2[i / 4];
                data[i++] = data2[i / 4];
                data[i++] = 255;
            }
            return dst;
        }
        function cvtColorGray2RGBA_ColorMap(_src) {
            var row = _src.row,
                col = _src.col;
            var dst = new Image_RGBA(row, col);
            data = dst.data;
            data2 = _src.data;
            for (i = 0; i < _src.row * _src.col * 4;) {

                var pix = data2[i / 4] * 2;

                data[i++] = color_map_r[pix] * 255;
                data[i++] = color_map_g[pix] * 255;
                data[i++] = color_map_b[pix] * 255;
                data[i++] = 255;
            }
            return dst;
        }
        function sobel(_src) {
            var SOBEL_CAP = 34;
            var height = _src.row;
            var width = _src.col;
            var in_image = _src.data;
            var dst = new Image_GRAY(height, width);
            var out_image = dst.data;
            for (y = 1; y < height - 1; y++) {
                for (x = 1; x < width - 1; x++) {
                    var val = ((in_image[width * (y - 1) + x + 1] - in_image[width * (y - 1) + x - 1]) +
                        (in_image[width * y + x + 1] - in_image[width * y + x - 1]) * 2 +
                        (in_image[width * (y + 1) + x + 1] - in_image[width * (y + 1) + x - 1]));

                    if (val > SOBEL_CAP)
                        val = SOBEL_CAP;
                    else if (val < -SOBEL_CAP)
                        val = -SOBEL_CAP;

                    out_image[width * y + x] = val + SOBEL_CAP;
                }
            }
            return dst;
        }

        function left_bm(left_src, right_src) {

            var height = left_src.row;
            var width = left_src.col;
            var halfWindow = 5;
            var dst = new Image_GRAY(height, width);
            var dispL = dst.data;
            var NumDisparity = 128;
            var INVALID_DISP_VAL = 0;

            var imgL = left_src.data;
            var imgR = right_src.data;

            for (y = halfWindow; y < height - halfWindow; y++) {
                for (x = halfWindow; x < width - halfWindow; x++) {
                    var min_costL = 32767;
                    dispL[y * width + x] = INVALID_DISP_VAL;
                    for (d = 0; d < Math.min(x - halfWindow, NumDisparity); d++) {
                        var win_cost = 0;
                        var diff = 0;
                        for (y1 = y - halfWindow; y1 <= y + halfWindow; y1++) {
                            for (x1 = x - halfWindow; x1 <= x + halfWindow; x1++) {
                                diff = Math.abs(imgL[y1 * width + x1] - imgR[y1 * width + x1 - d]);
                                win_cost += Math.abs(diff);
                            }
                        }
                        if (win_cost < min_costL) {
                            min_costL = win_cost;
                            dispL[y * width + x] = d;
                        }
                    }
                }
            }
            return dst;
        }

        function right_bm(left_src, right_src) {
            var height = left_src.row;
            var width = left_src.col;
            var halfWindow = 5;
            var dst = new Image_GRAY(height, width);
            var dispR = dst.data;
            var NumDisparity = 128;
            var INVALID_DISP_VAL = 0;

            var imgL = left_src.data;
            var imgR = right_src.data;

            for (y = halfWindow; y < height - halfWindow; y++) {
                for (x = halfWindow; x < width - halfWindow; x++) {
                    var min_costL = 32767;
                    dispR[y * width + x] = INVALID_DISP_VAL;
                    for (d = 0; d < Math.min(width - x - halfWindow, NumDisparity); d++) {
                        var win_cost = 0;
                        var diff = 0;
                        for (y1 = y - halfWindow; y1 <= y + halfWindow; y1++) {
                            for (x1 = x - halfWindow; x1 <= x + halfWindow; x1++) {
                                diff = Math.abs(imgR[y1 * width + x1] - imgL[y1 * width + x1 + d]);
                                win_cost += Math.abs(diff);
                            }
                        }
                        if (win_cost < min_costL) {
                            min_costL = win_cost;
                            dispR[y * width + x] = d;
                        }
                    }
                }
            }
            return dst;
        }
        function left_right_check(left_src, right_src) {
            var height = left_src.row;
            var width = left_src.col;
            var dst = new Image_GRAY(height, width);

            var disp = dst.data;
            var INVALID_DISP_VAL = 0;

            var disp_left = left_src.data;
            var disp_right = right_src.data;

            for (y = 0; y < height; y++) {
                for (x = 0; x < width; x++) {
                    disp[y * width + x] = disp_left[y * width + x];
                    var left = disp_left[y * width + x];
                    if (x - left > 0) {
                        var right = disp_right[y * width + x - left];
                        var dispDiff = Math.abs(left - right);
                        if (dispDiff > 1)
                            disp[y * width + x] = 0;

                    }
                }
            }
            return dst;
        }


        self.addEventListener("message", function (e) {
            var left_Mat = e.data[0];
            var right_Mat = e.data[1];
            var out_disp = worker_bm(left_Mat, right_Mat);
            postMessage(out_disp);
        }, false);
    </script>
    <script type="text/javascript" charset="utf-8">

        function imread(_image) {
            var width = _image.width,
                height = _image.height;
            var canvas = document.createElement('canvas');
            canvas.width = width;
            canvas.height = height;
            canvas.id = "temp_canvas";

            canvas.getContext("2d").drawImage(_image, 0, 0);
            var imageData = canvas.getContext("2d").getImageData(0, 0, width, height),
                tempMat = new Image_RGBA(height, width, imageData.data);
            imageData = null;
            canvas.getContext("2d").clearRect(0, 0, width, height);
            canvas = null;
            return tempMat;
        }

        function StereoBM(disp_Canvas, left_img, right_img) {
            var left_Ctx = disp_Canvas.getContext("2d");
            var left_Mat = imread(left_img);
            var right_Mat = imread(right_img);

            var bm_blob = new Blob([document.querySelector('#bm_worker').textContent]);
            var bm_url = window.URL.createObjectURL(bm_blob);
            worker = new Worker(bm_url);
            var msg = new Array(left_Mat, right_Mat);
            worker.postMessage(msg);
            document.getElementById("info_message").innerHTML = "Execute BM, it may take a long time, please wait patiently......";
            worker.onmessage = function (event) {
                if (typeof (event.data) == 'number') {
                    var bar = document.getElementById("bar");
                    var total = document.getElementById("total");
                    bar.style.width = event.data + "%";
                    total.innerHTML = "Progress:"+bar.style.width;
                }
                else {
                    var left_ImageRGBA = event.data;
                    disp_Canvas.width = left_Mat.col;
                    disp_Canvas.height = left_Mat.row;

                    imageData = left_Ctx.createImageData(left_Mat.col, right_Mat.row);
                    imageData.data.set(left_ImageRGBA.data);

                    left_Ctx.putImageData(imageData, 0, 0);
                    document.getElementById("info_message").innerHTML = "Done!";
                    worker.terminate();
                    worker = undefined;
                }
            };

        }


    </script>
</head>

<body>
    <div>
        Left Image: <input type="file" name="file" id="left_img_file_id" />
        <br>
        Right Image: <input type="file" name="file" id="right_img_file_id" />
        <br>
        <button type="submit" name="btn" value="提交" id="btnId" onclick="begin_bm()">Begin</button>
        <div class="container">
            <div id="bar" style="width:0%;"></div>
        </div>
        <span id="total"></span>
    </div>
    <canvas id="left_canvas" width="200" height="100"></canvas>
    <canvas id="right_canvas" width="200" height="100"></canvas>
    <br>
    <canvas id="disp_image" width="200" height="100"></canvas>
    <br>
    <div id="info_message">Binocular block matching algorithm, please select left and right image files</div>

    <script type="text/javascript" charset="utf-8">

        function begin_bm() {

            function read_image(image_file) {
                let p = new Promise(function (resolve, reject) {
                    const objFile = document.getElementById(image_file)
                    var image_reader = new FileReader();
                    image_reader.onload = function (e) {
                        resolve(image_reader.result);
                    };
                    image_reader.readAsDataURL(objFile.files[0]);
                });
                return p;

            }

            function load_image(image_url) {
                let p = new Promise(function (resolve, reject) {
                    var img = new Image();
                    img.onload = function () {
                        resolve(img);
                    }
                    img.src = image_url;
                });
                return p;
            };


            function show_canvas(canvas, dataUrl) {
                var ctx = canvas.getContext('2d');
                var img = new Image();
                img.onload = function () {
                    canvas.width = img.width;
                    canvas.height = img.height;
                    ctx.drawImage(img, 0, 0, img.width, img.height);
                }
                img.src = dataUrl;
            }

            if (document.getElementById("left_img_file_id").value === '') {
                alert('Please select the left image file!')
                return
            }
            if (document.getElementById("right_img_file_id").value === '') {
                alert('Please select the right image file!')
                return
            }
            var images_url = {};
            var images_data = {};
            var disp_Canvas = document.getElementById("disp_image");

            read_image('left_img_file_id').then(function (data) {
                show_canvas(document.getElementById('left_canvas'), data);
                images_url["left"] = data;
                return read_image('right_img_file_id');
            }).then(function (data) {
                show_canvas(document.getElementById('right_canvas'), data);
                images_url["right"] = data;
                return load_image(images_url["left"]);
            }).then(function (data) {
                images_data["left"] = data;
                return load_image(images_url["right"]);
            }).then(function (data) {
                images_data["right"] = data;
            }).then(function () {
                StereoBM(disp_Canvas, images_data["left"], images_data["right"]);
            });


        }

    </script>
</body>

</html>